//=============================================================================
/**
 * @file	gym_combat.c
 * @brief	格闘ジムギミック
 * @author	Nozomu Saito
 *
 * モジュール名：GYM_
 *
 */
//=============================================================================
#include "common.h"
#include "fieldsys.h"
#include "fieldmap_work.h"
#include "system/snd_tool.h"
#include "system/camera_move.h"
#include "include/savedata/gimmickwork.h"
#include "../fielddata/build_model/build_model_id.h"

#include "field_gimmick_def.h"
#include "sysflag_def.h"

#include "gym_def.h"

#include "gym_local.h"
#include "gym_init.h"

#include "gym.h"

#define CAMERA_SHIFT_X	(0x32000)
#define CAMERA_SHIFT_Z	(0x3A000)
#define CAM_MOVE_SYNC	(24)

typedef struct COMBAT_GYM_TEMP_WORK_tag
{
	FIELDSYS_WORK *fsys;
}COMBAT_GYM_TEMP_WORK;

typedef struct {
	int seq;							///<シーケンス保持ワーク
	FIELDSYS_WORK *fsys;
	CAM_MOV_CNT_PTR	CamMovPtr;
}EVENT_GYM_WORK;

static void CallFallMoveEvent(COMBAT_GYM_TEMP_WORK *ioCombatTemp);
static BOOL GMEVENT_MoveFallGymCombat(GMEVENT_CONTROL * event);

static u8 SetAnme(FIELDSYS_WORK * fsys);

//---------------------------------------------------------------------------
/**
 * @brief	格闘ジム:セットアップ
 *
 * @param	fsys	フィールドシステムポインタ
 *
 * @return	none
 */
//---------------------------------------------------------------------------
void GYM_SetupCombatGym(FIELDSYS_WORK *fsys)
{
	COMBAT_GYM_TEMP_WORK *combat_temp;
	GIMMICKWORK *work;
	COMBAT_GYM_WORK *combat_gym_work;

	//ここでギミックワークの中身を見る
	work = SaveData_GetGimmickWork(GameSystem_GetSaveData(fsys));
	combat_gym_work = (COMBAT_GYM_WORK*)GIMMICKWORK_Get(work, FLD_GIMMICK_COMBAT_GYM);

	//格闘ジム専用ワークをアロケートして、フィールドマップ汎用ワークポインタにあてる
	fsys->fldmap->Work = sys_AllocMemory(HEAPID_FIELD, sizeof(COMBAT_GYM_TEMP_WORK));
	//初期化
	MI_CpuClear8(fsys->fldmap->Work, sizeof(COMBAT_GYM_TEMP_WORK));
	combat_temp = fsys->fldmap->Work;

	combat_temp->fsys = fsys;

	//スイッチ切り替え状態を見て、アニメーションを切り替える
	if (combat_gym_work->HandleFlg){
		FLD_3D_ANM_DAT_PTR anm_dat;
		u8 anm_num;
		u8 i;
		//常駐アニメを切って、閉口アニメをセットし、ラストフレームでとめておく
		anm_num = SetAnme(fsys);
		for(i=0;i<anm_num;i++){
			anm_dat = F3DA_GetFld3DAnmPtr( BMID_ROOM_MG06_FL2, i, fsys->field_3d_anime);
			F3DA_SetStopFlg(anm_dat, TRUE);
			F3DA_SetLastFrame(anm_dat);
		}
		anm_dat = F3DA_GetFld3DAnmPtr( BMID_ROOM_MG06_SWC, 0, fsys->field_3d_anime);
		F3DA_SetStopFlg(anm_dat, TRUE);
		F3DA_SetLastFrame(anm_dat);
	}
}

//---------------------------------------------------------------------------
/**
 * @brief	格闘ジム:終了処理
 *
 * @param	fsys	フィールドシステムポインタ
 *
 * @return	none
 */
//---------------------------------------------------------------------------
void GYM_EndCombatGym(FIELDSYS_WORK *fsys)
{
	COMBAT_GYM_TEMP_WORK *combat_temp;
	combat_temp = (COMBAT_GYM_TEMP_WORK *)fsys->fldmap->Work;
	sys_FreeMemoryEz(combat_temp);
	fsys->fldmap->Work = NULL;
}

//---------------------------------------------------------------------------
/**
 * @brief	格闘ジム:ギミック発動
 *
 * @param	fsys	フィールドシステムポインタ
 *
 * @return	BOOL	TRUE:発動		FALSE:発動済
 */
//---------------------------------------------------------------------------
BOOL GYM_CheckCombatGymEvt(FIELDSYS_WORK *fsys)
{
	COMBAT_GYM_TEMP_WORK *combat_temp;
	COMBAT_GYM_WORK *combat_gym_work;
	//ギミックワークを見る
	{
		int id;
		GIMMICKWORK *work;

		//ギミックワーク取得
		work = SaveData_GetGimmickWork(GameSystem_GetSaveData(fsys));
		//ギミックコードを取得
		id = GIMMICKWORK_GetAssignID(work);

		if (id != FLD_GIMMICK_COMBAT_GYM){
			return FALSE;					//格闘ジムギミック無し
		}
		combat_gym_work = (COMBAT_GYM_WORK*)GIMMICKWORK_Get(work, FLD_GIMMICK_COMBAT_GYM);
	}

	combat_temp = (COMBAT_GYM_TEMP_WORK *)fsys->fldmap->Work;
	if (combat_temp == NULL){
		return FALSE;
	}

	if(!combat_gym_work->HandleFlg){
		//未発動なので処理
		CallFallMoveEvent(combat_temp);
		return TRUE;
	}

	return FALSE;
}

//---------------------------------------------------------------------------
/**
 * @brief	格闘ジム:雨樋イベントコール
 *
 * @param	ioCombatTemp	格闘ジムテンポラリワーク
 *
 * @return	none
 */
//---------------------------------------------------------------------------
static void CallFallMoveEvent(COMBAT_GYM_TEMP_WORK *ioCombatTemp)
{
	EVENT_GYM_WORK * egw;

	GIMMICKWORK *work;
	COMBAT_GYM_WORK *combat_gym_work;
	work = SaveData_GetGimmickWork(GameSystem_GetSaveData(ioCombatTemp->fsys));
	combat_gym_work = (COMBAT_GYM_WORK*)GIMMICKWORK_Get(work, FLD_GIMMICK_COMBAT_GYM);

	egw = sys_AllocMemoryLo(HEAPID_WORLD, sizeof(EVENT_GYM_WORK));
	egw->seq = 0;

	//ハンドル回したフラグ成立
	combat_gym_work->HandleFlg = 1;

	FieldEvent_Call(ioCombatTemp->fsys->event, GMEVENT_MoveFallGymCombat, egw);
}

//---------------------------------------------------------------------------
/**
 * @brief	格闘ジム:雨樋の移動
 *
 * @param	event	イベントポインタ
 *
 * @return	BOOL TRUE:イベント終了	FALSE:イベント継続
 */
//---------------------------------------------------------------------------
static BOOL GMEVENT_MoveFallGymCombat(GMEVENT_CONTROL * event)
{
	FIELD_OBJ_PTR fop;
	FIELDSYS_WORK * fsys = FieldEvent_GetFieldSysWork(event);
	EVENT_GYM_WORK * egw = FieldEvent_GetSpecialWork(event);
	COMBAT_GYM_TEMP_WORK *combat_temp;

	combat_temp = (COMBAT_GYM_TEMP_WORK *)fsys->fldmap->Work;
	fop = Player_FieldOBJGet( fsys->player );
	switch (egw->seq) {
	case 0:
		//カメラパラメータを作成して、リクエスト
		{
			CAMERA_MOVE_PARAM param;
			VecFx32 shift = {CAMERA_SHIFT_X,0,CAMERA_SHIFT_Z};
			CAMERA_ANGLE ang = GFC_GetCameraAngle(fsys->camera_ptr);
			param.Angle = ang.x;
			param.PerspWay = GFC_GetCameraPerspWay(fsys->camera_ptr);
			param.Length = shift;
			param.Distance = GFC_GetCameraDistance(fsys->camera_ptr);

			egw->CamMovPtr = CamMove_Init(HEAPID_FIELD, fsys->camera_ptr);
			CamMove_Request(egw->CamMovPtr, &param, CAM_MOVE_SYNC);
		}
		(egw->seq)	++;
		break;
	case 1:	//カメラ移動待ち
		if ( CamMove_CheckFinished(egw->CamMovPtr) ){
			//解放
			CamMove_Delete( egw->CamMovPtr );
			(egw->seq)	++;
		}
		break;
	case 2:	//アニメ登録
		{
			int i;
			u8 anm_num;
			FLD_3D_ANM_DAT_PTR anm_dat;
			anm_num = SetAnme(fsys);
			for(i=0;i<anm_num;i++){
				anm_dat = F3DA_GetFld3DAnmPtr( BMID_ROOM_MG06_FL2, i, fsys->field_3d_anime);
				//アニメの頭だしとループ数を設定
				F3DA_SetAnimeLoopMax(anm_dat, 1);
				F3DA_SetStartFrame(anm_dat);
			}
			anm_dat = F3DA_GetFld3DAnmPtr( BMID_ROOM_MG06_SWC, 0, fsys->field_3d_anime);
			//アニメの頭だしとループ数を設定
			F3DA_SetAnimeLoopMax(anm_dat, 1);
			F3DA_SetStartFrame(anm_dat);
			(egw->seq) ++;
		}
		break;
	case 3:
		{
			FLD_3D_ANM_DAT_PTR anm_dat;
			//アニメ終了待ち 終了の待ち方は、ハンドルアニメの終了で検出
			anm_dat = F3DA_GetFld3DAnmPtr( BMID_ROOM_MG06_SWC, 0, fsys->field_3d_anime);
			if ( F3DA_IsAnimeEnd(anm_dat) ){
				(egw->seq) ++;
			}
		}
		break;
	case 4:
		//カメラパラメータを作成して、リクエスト
		{
			CAMERA_MOVE_PARAM param;
			VecFx32 shift = {0,0,0};
			CAMERA_ANGLE ang = GFC_GetCameraAngle(fsys->camera_ptr);
			param.Angle = ang.x;
			param.PerspWay = GFC_GetCameraPerspWay(fsys->camera_ptr);
			param.Length = shift;
			param.Distance = GFC_GetCameraDistance(fsys->camera_ptr);

			egw->CamMovPtr = CamMove_Init(HEAPID_FIELD, fsys->camera_ptr);
			CamMove_Request(egw->CamMovPtr, &param, CAM_MOVE_SYNC);
		}
		(egw->seq)	++;
		break;
	case 5:	//カメラ移動待ち
		if ( CamMove_CheckFinished(egw->CamMovPtr) ){
			//解放
			CamMove_Delete( egw->CamMovPtr );
			(egw->seq)	++;
		}
		break;
	case 6:
		sys_FreeMemoryEz(egw);
		return TRUE;
	}
	return FALSE;
}

//---------------------------------------------------------------------------
/**
 * @brief	アニメセット
 *
 * @param	fsys		フィールドシステムポインタ
 *
 * @return	u8			アニメ数
 */
//---------------------------------------------------------------------------
static u8 SetAnme(FIELDSYS_WORK * fsys)
{
	int i;
	F_OBJ_DATA	*fall;
	F_OBJ_DATA	*fall_dmy;
	F_OBJ_DATA	*handle;

	u8 anm_num;
	//雨樋ＯＢＪ取得
	fall = F_RES_OBJ_GetRenderObjPtr(fsys->FldResObjMng, BMID_ROOM_MG06_FL1);
	fall_dmy = F_RES_OBJ_GetRenderObjPtr(fsys->FldResObjMng, BMID_ROOM_MG06_FL2);
	//ハンドルＯＢＪ取得
	handle = F_RES_OBJ_GetRenderObjPtr(fsys->FldResObjMng, BMID_ROOM_MG06_SWC);

	//指定ＯＢＪアニメ数を入手
	anm_num = F3DA_GetAnimeNum(fsys->field_3d_anime, BMID_ROOM_MG06_FL1);
	OS_Printf("切り離すアニメ数%d\n",anm_num);
	//アニメパージ
	for(i=0;i<anm_num;i++){
		F3DA_RemoveFld3DAnime(	fsys->field_3d_anime,
								&fall->RenderObj,
								BMID_ROOM_MG06_FL1,
								i	);
	}
	//指定ＯＢＪアニメ数を入手
	anm_num = F3DA_GetAnimeNum(fsys->field_3d_anime, BMID_ROOM_MG06_FL2);
	OS_Printf("追加アニメ数%d\n",anm_num);
	for(i=0;i<anm_num;i++){
		F3DA_SetFld3DAnime(	BMID_ROOM_MG06_FL2,
							i,
							TRUE,
							&fall->RenderObj,
							fsys->field_3d_anime);
	}

	//ハンドルアニメセット（ハンドルアニメは１つであることが前提の処理。アニメ数をカウントしてない）
	F3DA_SetFld3DAnime(	BMID_ROOM_MG06_SWC,
						0,
						TRUE,
						&handle->RenderObj,
						fsys->field_3d_anime);

	return anm_num;
}